import { useCallback, useEffect, useRef } from "react";
import { useCallbackRef } from "./useCallbackRef";

/**
 * 防抖函数
 * @param func 需要防抖的函数
 * @param delay 延后执行，如果此时间内有新的调用，则重新计算延后时间
 * @returns 新的已防抖的函数
 */
export function useDebounce<T extends Callable>(
  fn: T,
  delay: number,
  immediate?: boolean
) {
  const timerRef = useRef(0);
  const callbackFn = useCallbackRef(fn);
  // 在组件卸载时清除定时器
  useEffect(() => {
    return () => {
      clearTimeout(timerRef.current);
    };
  }, []);

  return useCallback(
    (...args: Parameters<T>) => {
      immediate && !timerRef.current && callbackFn(...args);
      clearTimeout(timerRef.current);
      timerRef.current = window.setTimeout(() => callbackFn(...args), delay);
    },
    [callbackFn, delay]
  );
}

/**
 * 节流函数
 * @param fn 需要节流的函数
 * @param delay 间隔多久执行一次
 * @returns 新的已节流的函数
 */
export function useThrottle<T extends Callable>(fn: T, delay: number) {
  const callbackFn = useCallbackRef(fn); // 用于持有最新的 `fn`
  const isThrottled = useRef(false); // 用 useRef 替代局部变量 `click`
  const timerRef = useRef(0); // 用于存储定时器引用

  // 清理定时器，避免内存泄漏
  useEffect(() => {
    return () => {
      clearTimeout(timerRef.current);
    };
  }, []);

  return useCallback(
    (...args: Parameters<T>) => {
      if (isThrottled.current) return;
      isThrottled.current = true;
      callbackFn(...args);

      // 启动定时器，延时后重置节流状态
      timerRef.current = window.setTimeout(() => {
        isThrottled.current = false;
      }, delay);
    },
    [callbackFn, delay]
  );
}

type Callable = (...args: never[]) => void;
